home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / os_amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-14  |  32.7 KB  |  1,590 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * os_amiga.c
  12.  *
  13.  * Amiga system-dependent routines.
  14.  */
  15.  
  16. #include "vim.h"
  17.  
  18. #ifdef Window
  19. # undef Window    /* Amiga has its own Window definition */
  20. #endif
  21.  
  22. #ifdef HAVE_FCNTL_H
  23. # include <fcntl.h>
  24. #endif
  25.  
  26. #undef TRUE        /* will be redefined by exec/types.h */
  27. #undef FALSE
  28.  
  29. #ifndef LATTICE
  30. # include <exec/types.h>
  31. # include <exec/exec.h>
  32. # include <libraries/dos.h>
  33. # include <libraries/dosextens.h>
  34. # include <intuition/intuition.h>
  35. #else
  36. # include <proto/dos.h>
  37. # include <libraries/dosextens.h>
  38. # include <proto/intuition.h>
  39. # include <proto/exec.h>
  40. #endif
  41.  
  42. #include <exec/memory.h>
  43.  
  44. #include <dos/dostags.h>        /* for 2.0 functions */
  45. #include <dos/dosasl.h>
  46.  
  47. #if defined(LATTICE) && !defined(SASC) && defined(FEAT_ARP)
  48. # include <libraries/arp_pragmas.h>
  49. #endif
  50.  
  51. /*
  52.  * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
  53.  */
  54. #undef    TRUE
  55. #define TRUE (1)
  56. #undef    FALSE
  57. #define FALSE (0)
  58.  
  59. #ifndef AZTEC_C
  60. static long dos_packet __ARGS((struct MsgPort *, long, long));
  61. #endif
  62. static int lock2name __ARGS((BPTR lock, char_u *buf, long   len));
  63. static void out_num __ARGS((long n));
  64. static struct FileInfoBlock *get_fib __ARGS((char_u *));
  65. static int sortcmp __ARGS((char **a, char **b));
  66.  
  67. static BPTR        raw_in = (BPTR)NULL;
  68. static BPTR        raw_out = (BPTR)NULL;
  69. static int        close_win = FALSE;  /* set if Vim opened the window */
  70.  
  71. struct IntuitionBase    *IntuitionBase = NULL;
  72. #ifdef FEAT_ARP
  73. struct ArpBase        *ArpBase = NULL;
  74. #endif
  75.  
  76. static struct Window    *wb_window;
  77. static char_u        *oldwindowtitle = NULL;
  78.  
  79. #ifdef FEAT_ARP
  80. int            dos2 = FALSE;        /* Amiga DOS 2.0x or higher */
  81. #endif
  82. int            size_set = FALSE;   /* set to TRUE if window size was set */
  83.  
  84.     void
  85. win_resize_on()
  86. {
  87.     OUT_STR_NF("\033[12{");
  88. }
  89.  
  90.     void
  91. win_resize_off()
  92. {
  93.     OUT_STR_NF("\033[12}");
  94. }
  95.  
  96.     void
  97. mch_write(p, len)
  98.     char_u    *p;
  99.     int        len;
  100. {
  101.     Write(raw_out, (char *)p, (long)len);
  102. }
  103.  
  104. /*
  105.  * mch_inchar(): low level input funcion.
  106.  * Get a characters from the keyboard.
  107.  * If time == 0 do not wait for characters.
  108.  * If time == n wait a short time for characters.
  109.  * If time == -1 wait forever for characters.
  110.  *
  111.  * Return number of characters read.
  112.  */
  113.     int
  114. mch_inchar(buf, maxlen, time)
  115.     char_u  *buf;
  116.     int        maxlen;
  117.     long    time;        /* milli seconds */
  118. {
  119.     int        len;
  120.     long    utime;
  121. #ifdef FEAT_AUTOCMD
  122.     static int    once_already = 0;
  123. #endif
  124.  
  125.     if (time >= 0)
  126.     {
  127.     if (time == 0)
  128.         utime = 100L;        /* time = 0 causes problems in DOS 1.2 */
  129.     else
  130.         utime = time * 1000L;   /* convert from milli to micro secs */
  131.     if (WaitForChar(raw_in, utime) == 0)    /* no character available */
  132.     {
  133. #ifdef FEAT_AUTOCMD
  134.         once_already = 0;
  135. #endif
  136.         return 0;
  137.     }
  138.     }
  139.     else    /* time == -1 */
  140.     {
  141. #ifdef FEAT_AUTOCMD
  142.     if (once_already == 2)
  143.         updatescript(0);
  144.     else if (once_already == 1)
  145.     {
  146.         setcursor();
  147.         once_already = 2;
  148.         return 0;
  149.     }
  150.     else
  151. #endif
  152.     /*
  153.      * If there is no character available within 2 seconds (default)
  154.      * write the autoscript file to disk
  155.      */
  156.         if (WaitForChar(raw_in, p_ut * 1000L) == 0)
  157.     {
  158. #ifdef FEAT_AUTOCMD
  159.         if (has_cursorhold() && get_real_state() == NORMAL_BUSY)
  160.         {
  161.         apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, FALSE, curbuf);
  162.         update_screen(VALID);
  163.         once_already = 1;
  164.         return 0;
  165.         }
  166.         else
  167. #endif
  168.         updatescript(0);
  169.     }
  170.     }
  171.  
  172.     for (;;)        /* repeat until we got a character */
  173.     {
  174.     len = Read(raw_in, (char *)buf, (long)maxlen);
  175.     if (len > 0)
  176.     {
  177. #ifdef FEAT_AUTOCMD
  178.         once_already = 0;
  179. #endif
  180. #ifdef FEAT_MBYTE
  181.         /* Convert from 'termencoding' to 'encoding'. */
  182.         if (input_conv.vc_type != CONV_NONE)
  183.         len = convert_input(buf, len, maxlen);
  184. #endif
  185.         return len;
  186.     }
  187.     }
  188. }
  189.  
  190. /*
  191.  * return non-zero if a character is available
  192.  */
  193.     int
  194. mch_char_avail()
  195. {
  196.     return (WaitForChar(raw_in, 100L) != 0);
  197. }
  198.  
  199. /*
  200.  * Return amount of memory still available.
  201.  */
  202.     long_u
  203. mch_avail_mem(special)
  204.     int        special;
  205. {
  206.     return (long_u)AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY);
  207. }
  208.  
  209.     void
  210. mch_delay(msec, ignoreinput)
  211.     long    msec;
  212.     int        ignoreinput;
  213. {
  214. #ifndef LATTICE        /* SAS declares void Delay(UNLONG) */
  215.     void        Delay __ARGS((long));
  216. #endif
  217.  
  218.     if (msec > 0)
  219.     {
  220.     if (ignoreinput)
  221.         Delay(msec / 20L);        /* Delay works with 20 msec intervals */
  222.     else
  223.         WaitForChar(raw_in, msec * 1000L);
  224.     }
  225. }
  226.  
  227. /*
  228.  * We have no job control, fake it by starting a new shell.
  229.  */
  230.     void
  231. mch_suspend()
  232. {
  233.     suspend_shell();
  234. }
  235.  
  236. #define DOS_LIBRARY    ((UBYTE *) "dos.library")
  237.  
  238.     void
  239. mch_init()
  240. {
  241.     static char        intlibname[] = "intuition.library";
  242.  
  243. #ifdef AZTEC_C
  244.     Enable_Abort = 0;        /* disallow vim to be aborted */
  245. #endif
  246.     Columns = 80;
  247.     Rows = 24;
  248.  
  249.     /*
  250.      * Set input and output channels, unless we have opened our own window
  251.      */
  252.     if (raw_in == (BPTR)NULL)
  253.     {
  254.     raw_in = Input();
  255.     raw_out = Output();
  256.     /*
  257.      * If Input() is not interactive, then Output() will be (because of
  258.      * check in mch_check_win()).  Used for "Vim -".
  259.      * Also check the other way around, for "Vim -h | more".
  260.      */
  261.     if (!IsInteractive(raw_in))
  262.         raw_in = raw_out;
  263.     else if (!IsInteractive(raw_out))
  264.         raw_out = raw_in;
  265.     }
  266.  
  267.     out_flush();
  268.  
  269.     wb_window = NULL;
  270.     if ((IntuitionBase = (struct IntuitionBase *)
  271.                 OpenLibrary((UBYTE *)intlibname, 0L)) == NULL)
  272.     {
  273.     mch_errmsg(_("cannot open "));
  274.     mch_errmsg(intlibname);
  275.     mch_errmsg("!?\n");
  276.     mch_exit(3);
  277.     }
  278. }
  279.  
  280. #include <workbench/startup.h>
  281.  
  282. /*
  283.  * Check_win checks whether we have an interactive window.
  284.  * If not, a new window is opened with the newcli command.
  285.  * If we would open a window ourselves, the :sh and :! commands would not
  286.  * work properly (Why? probably because we are then running in a background
  287.  * CLI). This also is the best way to assure proper working in a next
  288.  * Workbench release.
  289.  *
  290.  * For the -f option (foreground mode) we open our own window and disable :sh.
  291.  * Otherwise the calling program would never know when editing is finished.
  292.  */
  293. #define BUF2SIZE 320        /* length of buffer for argument with complete path */
  294.  
  295.     int
  296. mch_check_win(argc, argv)
  297.     int argc;
  298.     char **argv;
  299. {
  300.     int            i;
  301.     BPTR        nilfh, fh;
  302.     char_u        buf1[20];
  303.     char_u        buf2[BUF2SIZE];
  304.     static char_u   *(constrings[3]) = {(char_u *)"con:0/0/662/210/",
  305.                     (char_u *)"con:0/0/640/200/",
  306.                     (char_u *)"con:0/0/320/200/"};
  307.     static char_u   winerr[] = _("VIM: Can't open window!\n");
  308.     struct WBArg    *argp;
  309.     int            ac;
  310.     char        *av;
  311.     char_u        *device = NULL;
  312.     int            exitval = 4;
  313.     struct Library  *DosBase;
  314.     int            usewin = FALSE;
  315.  
  316. /*
  317.  * check if we are running under DOS 2.0x or higher
  318.  */
  319.     if (DosBase = OpenLibrary(DOS_LIBRARY, 37L))
  320.     {
  321.     CloseLibrary(DosBase);
  322. #ifdef FEAT_ARP
  323.     dos2 = TRUE;
  324. #endif
  325.     }
  326.     else        /* without arp functions we NEED 2.0 */
  327.     {
  328. #ifndef FEAT_ARP
  329.     mch_errmsg(_("Need Amigados version 2.04 or later\n"));
  330.     exit(3);
  331. #else
  332.             /* need arp functions for dos 1.x */
  333.     if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion)))
  334.     {
  335.         fprintf(stderr, _("Need %s version %ld\n"), ArpName, ArpVersion);
  336.         exit(3);
  337.     }
  338. #endif
  339.     }
  340.  
  341.     /*
  342.      * scan argv[] for the "-f" and "-d" arguments
  343.      */
  344.     for (i = 1; i < argc; ++i)
  345.     if (argv[i][0] == '-')
  346.     {
  347.         switch (argv[i][1])
  348.         {
  349.         case 'f':
  350.         usewin = TRUE;
  351.         break;
  352.  
  353.         case 'd':
  354.         if (i < argc - 1
  355. #ifdef FEAT_DIFF
  356.             /* require using "-dev", "-d" means diff mode */
  357.             && argv[i][2] == 'e' && argv[i][3] == 'v'
  358. #endif
  359.            )
  360.             device = (char_u *)argv[i + 1];
  361.         break;
  362.         }
  363.     }
  364.  
  365. /*
  366.  * If we were not started from workbench, do not have a "-d" or "-dev"
  367.  * argument and we have been started with an interactive window, use that
  368.  * window.
  369.  */
  370.     if (argc != 0
  371.         && device == NULL
  372.         && (IsInteractive(Input()) || IsInteractive(Output())))
  373.     return OK;
  374.  
  375. /*
  376.  * When given the "-f" argument, we open our own window. We can't use the
  377.  * newcli trick below, because the calling program (mail, rn, etc.) would not
  378.  * know when we are finished.
  379.  */
  380.     if (usewin)
  381.     {
  382.     /*
  383.      * Try to open a window. First try the specified device.
  384.      * Then try a 24 line 80 column window.
  385.      * If that fails, try two smaller ones.
  386.      */
  387.     for (i = -1; i < 3; ++i)
  388.     {
  389.         if (i >= 0)
  390.         device = constrings[i];
  391.         if (device != NULL && (raw_in = Open((UBYTE *)device,
  392.                        (long)MODE_NEWFILE)) != (BPTR)NULL)
  393.         break;
  394.     }
  395.     if (raw_in == (BPTR)NULL)    /* all three failed */
  396.     {
  397.         mch_errmsg((char *)winerr);
  398.         goto exit;
  399.     }
  400.     raw_out = raw_in;
  401.     close_win = TRUE;
  402.     return OK;
  403.     }
  404.  
  405.     if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL)
  406.     {
  407.     mch_errmsg(_("Cannot open NIL:\n"));
  408.     goto exit;
  409.     }
  410.  
  411.     /*
  412.      * Make a unique name for the temp file (which we will not delete!).
  413.      * Use a pointer on the stack (nobody else will be using it).
  414.      */
  415.     sprintf((char *)buf1, "t:nc%ld", (char *)buf1);
  416.     if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL)
  417.     {
  418.     mch_errmsg(_("Cannot create "));
  419.     mch_errmsg((char *)buf1);
  420.     mch_errmsg("\n");
  421.     goto exit;
  422.     }
  423.     /*
  424.      * Write the command into the file, put quotes around the arguments that
  425.      * have a space in them.
  426.      */
  427.     if (argc == 0)    /* run from workbench */
  428.     ac = ((struct WBStartup *)argv)->sm_NumArgs;
  429.     else
  430.     ac = argc;
  431.     for (i = 0; i < ac; ++i)
  432.     {
  433.     if (argc == 0)
  434.     {
  435.         *buf2 = NUL;
  436.         argp = &(((struct WBStartup *)argv)->sm_ArgList[i]);
  437.         if (argp->wa_Lock)
  438.         (void)lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1));
  439. #ifdef FEAT_ARP
  440.         if (dos2)        /* use 2.0 function */
  441. #endif
  442.         AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1));
  443. #ifdef FEAT_ARP
  444.         else        /* use arp function */
  445.         TackOn((char *)buf2, argp->wa_Name);
  446. #endif
  447.         av = (char *)buf2;
  448.     }
  449.     else
  450.         av = argv[i];
  451.  
  452.     /* skip '-d' or "-dev" option */
  453.     if (av[0] == '-' && av[1] == 'd'
  454. #ifdef FEAT_DIFF
  455.         && av[2] == 'e' && av[3] == 'v'
  456. #endif
  457.         )
  458.     {
  459.         ++i;
  460.         continue;
  461.     }
  462.     if (vim_strchr((char_u *)av, ' '))
  463.         Write(fh, "\"", 1L);
  464.     Write(fh, av, (long)strlen(av));
  465.     if (vim_strchr((char_u *)av, ' '))
  466.         Write(fh, "\"", 1L);
  467.     Write(fh, " ", 1L);
  468.     }
  469.     Write(fh, "\nendcli\n", 8L);
  470.     Close(fh);
  471.  
  472. /*
  473.  * Try to open a new cli in a window. If "-d" or "-dev" argument was given try
  474.  * to open the specified device. Then try a 24 line 80 column window.  If that
  475.  * fails, try two smaller ones.
  476.  */
  477.     for (i = -1; i < 3; ++i)
  478.     {
  479.     if (i >= 0)
  480.         device = constrings[i];
  481.     else if (device == NULL)
  482.         continue;
  483.     sprintf((char *)buf2, "newcli <nil: >nil: %s from %s", (char *)device, (char *)buf1);
  484. #ifdef FEAT_ARP
  485.     if (dos2)
  486.     {
  487. #endif
  488.         if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE))
  489.         break;
  490. #ifdef FEAT_ARP
  491.     }
  492.     else
  493.     {
  494.         if (Execute((UBYTE *)buf2, nilfh, nilfh))
  495.         break;
  496.     }
  497. #endif
  498.     }
  499.     if (i == 3)        /* all three failed */
  500.     {
  501.     DeleteFile((UBYTE *)buf1);
  502.     mch_errmsg((char *)winerr);
  503.     goto exit;
  504.     }
  505.     exitval = 0;    /* The Execute succeeded: exit this program */
  506.  
  507. exit:
  508. #ifdef FEAT_ARP
  509.     if (ArpBase)
  510.     CloseLibrary((struct Library *) ArpBase);
  511. #endif
  512.     exit(exitval);
  513.     /* NOTREACHED */
  514.     return FAIL;
  515. }
  516.  
  517. /*
  518.  * Return TRUE if the input comes from a terminal, FALSE otherwise.
  519.  * We fake there is a window, because we can always open one!
  520.  */
  521.     int
  522. mch_input_isatty()
  523. {
  524.     return TRUE;
  525. }
  526.  
  527. /*
  528.  * fname_case(): Set the case of the file name, if it already exists.
  529.  *         This will cause the file name to remain exactly the same.
  530.  */
  531. /*ARGSUSED*/
  532.     void
  533. fname_case(name, len)
  534.     char_u    *name;
  535.     int        len;        /* buffer size, ignored here */
  536. {
  537.     struct FileInfoBlock    *fib;
  538.     size_t            flen;
  539.  
  540.     fib = get_fib(name);
  541.     if (fib != NULL)
  542.     {
  543.     flen = STRLEN(name);
  544.     if (flen == strlen(fib->fib_FileName))    /* safety check */
  545.         mch_memmove(name, fib->fib_FileName, flen);
  546.     vim_free(fib);
  547.     }
  548. }
  549.  
  550. /*
  551.  * Get the FileInfoBlock for file "fname"
  552.  * The returned structure has to be free()d.
  553.  * Returns NULL on error.
  554.  */
  555.     static struct FileInfoBlock *
  556. get_fib(fname)
  557.     char_u *fname;
  558. {
  559.     BPTR            flock;
  560.     struct FileInfoBlock    *fib;
  561.  
  562.     if (fname == NULL)        /* safety check */
  563.     return NULL;
  564.     fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
  565.     if (fib != NULL)
  566.     {
  567.     flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  568.     if (flock == (BPTR)NULL || !Examine(flock, fib))
  569.     {
  570.         vim_free(fib);  /* in case of an error the memory is freed here */
  571.         fib = NULL;
  572.     }
  573.     if (flock)
  574.         UnLock(flock);
  575.     }
  576.     return fib;
  577. }
  578.  
  579. #ifdef FEAT_TITLE
  580. /*
  581.  * set the title of our window
  582.  * icon name is not set
  583.  */
  584.     void
  585. mch_settitle(title, icon)
  586.     char_u  *title;
  587.     char_u  *icon;
  588. {
  589.     if (wb_window != NULL && title != NULL)
  590.     SetWindowTitles(wb_window, (UBYTE *)title, (UBYTE *)-1L);
  591. }
  592.  
  593. /*
  594.  * Restore the window/icon title.
  595.  * which is one of:
  596.  *  1  Just restore title
  597.  *  2  Just restore icon (which we don't have)
  598.  *  3  Restore title and icon (which we don't have)
  599.  */
  600.     void
  601. mch_restore_title(which)
  602.     int which;
  603. {
  604.     if (which & 1)
  605.     mch_settitle(oldwindowtitle, NULL);
  606. }
  607.  
  608.     int
  609. mch_can_restore_title()
  610. {
  611.     return (wb_window != NULL);
  612. }
  613.  
  614.     int
  615. mch_can_restore_icon()
  616. {
  617.     return FALSE;
  618. }
  619. #endif
  620.  
  621. /*
  622.  * Insert user name in s[len].
  623.  */
  624.     int
  625. mch_get_user_name(s, len)
  626.     char_u  *s;
  627.     int        len;
  628. {
  629.     *s = NUL;
  630.     return FAIL;
  631. }
  632.  
  633. /*
  634.  * Insert host name is s[len].
  635.  */
  636.     void
  637. mch_get_host_name(s, len)
  638.     char_u  *s;
  639.     int        len;
  640. {
  641.     STRNCPY(s, "Amiga", len);
  642. }
  643.  
  644. /*
  645.  * return process ID
  646.  */
  647.     long
  648. mch_get_pid()
  649. {
  650.     return (long)0;
  651. }
  652.  
  653. /*
  654.  * Get name of current directory into buffer 'buf' of length 'len' bytes.
  655.  * Return OK for success, FAIL for failure.
  656.  */
  657.     int
  658. mch_dirname(buf, len)
  659.     char_u    *buf;
  660.     int        len;
  661. {
  662.     return mch_FullName((char_u *)"", buf, len, FALSE);
  663. }
  664.  
  665. /*
  666.  * get absolute file name into buffer 'buf' of length 'len' bytes
  667.  *
  668.  * return FAIL for failure, OK otherwise
  669.  */
  670.     int
  671. mch_FullName(fname, buf, len, force)
  672.     char_u    *fname, *buf;
  673.     int        len;
  674.     int        force;
  675. {
  676.     BPTR    l;
  677.     int        retval = FAIL;
  678.     int        i;
  679.  
  680.     /* Lock the file.  If it exists, we can get the exact name. */
  681.     if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)) != (BPTR)0)
  682.     {
  683.     retval = lock2name(l, buf, (long)len - 1);
  684.     UnLock(l);
  685.     }
  686.     else if (force || !mch_isFullName(fname))        /* not a full path yet */
  687.     {
  688.     /*
  689.      * If the file cannot be locked (doesn't exist), try to lock the
  690.      * current directory and concatenate the file name.
  691.      */
  692.     if ((l = Lock((UBYTE *)"", (long)ACCESS_READ)) != (BPTR)NULL)
  693.     {
  694.         retval = lock2name(l, buf, (long)len);
  695.         UnLock(l);
  696.         if (retval == OK)
  697.         {
  698.         i = STRLEN(buf);
  699.         /* Concatenate the fname to the directory.  Don't add a slash
  700.          * if fname is empty, but do change "" to "/". */
  701.         if (i == 0 || *fname != NUL)
  702.         {
  703.             if (i < len - 1 && (i == 0 || buf[i - 1] != ':'))
  704.             buf[i++] = '/';
  705.             STRNCPY(buf + i, fname, len - i);
  706.         }
  707.         }
  708.     }
  709.     }
  710.     if (*buf == 0 || *buf == ':')
  711.     retval = FAIL;    /* something failed; use the file name */
  712.     return retval;
  713. }
  714.  
  715. /*
  716.  * Return TRUE if "fname" does not depend on the current directory.
  717.  */
  718.     int
  719. mch_isFullName(fname)
  720.     char_u    *fname;
  721. {
  722.     return (vim_strchr(fname, ':') != NULL && *fname != ':');
  723. }
  724.  
  725. /*
  726.  * Get the full file name from a lock. Use 2.0 function if possible, because
  727.  * the arp function has more restrictions on the path length.
  728.  *
  729.  * return FAIL for failure, OK otherwise
  730.  */
  731.     static int
  732. lock2name(lock, buf, len)
  733.     BPTR    lock;
  734.     char_u  *buf;
  735.     long    len;
  736. {
  737. #ifdef FEAT_ARP
  738.     if (dos2)            /* use 2.0 function */
  739. #endif
  740.     return ((int)NameFromLock(lock, (UBYTE *)buf, len) ? OK : FAIL);
  741. #ifdef FEAT_ARP
  742.     else        /* use arp function */
  743.     return ((int)PathName(lock, (char *)buf, (long)(len/32)) ? OK : FAIL);
  744. #endif
  745. }
  746.  
  747. /*
  748.  * get file permissions for 'name'
  749.  * Returns -1 when it doesn't exist.
  750.  */
  751.     long
  752. mch_getperm(name)
  753.     char_u    *name;
  754. {
  755.     struct FileInfoBlock    *fib;
  756.     long            retval = -1;
  757.  
  758.     fib = get_fib(name);
  759.     if (fib != NULL)
  760.     {
  761.     retval = fib->fib_Protection;
  762.     vim_free(fib);
  763.     }
  764.     return retval;
  765. }
  766.  
  767. /*
  768.  * set file permission for 'name' to 'perm'
  769.  *
  770.  * return FAIL for failure, OK otherwise
  771.  */
  772.     int
  773. mch_setperm(name, perm)
  774.     char_u    *name;
  775.     long    perm;
  776. {
  777.     perm &= ~FIBF_ARCHIVE;        /* reset archived bit */
  778.     return (SetProtection((UBYTE *)name, (long)perm) ? OK : FAIL);
  779. }
  780.  
  781. /*
  782.  * Set hidden flag for "name".
  783.  */
  784.     void
  785. mch_hide(name)
  786.     char_u    *name;
  787. {
  788.     /* can't hide a file */
  789. }
  790.  
  791. /*
  792.  * return FALSE if "name" is not a directory
  793.  * return TRUE if "name" is a directory.
  794.  * return FALSE for error.
  795.  */
  796.     int
  797. mch_isdir(name)
  798.     char_u    *name;
  799. {
  800.     struct FileInfoBlock    *fib;
  801.     int                retval = FALSE;
  802.  
  803.     fib = get_fib(name);
  804.     if (fib != NULL)
  805.     {
  806.     retval = ((fib->fib_DirEntryType >= 0) ? TRUE : FALSE);
  807.     vim_free(fib);
  808.     }
  809.     return retval;
  810. }
  811.  
  812. /*
  813.  * Create directory "name".
  814.  */
  815.     void
  816. mch_mkdir(name)
  817.     char_u    *name;
  818. {
  819.     BPTR    lock;
  820.  
  821.     lock = CreateDir(name);
  822.     if (lock != NULL)
  823.     UnLock(lock);
  824. }
  825.  
  826. #if defined(FEAT_EVAL) || defined(PROTO)
  827. /*
  828.  * Return 1 if "name" can be executed, 0 if not.
  829.  * Return -1 if unknown.
  830.  */
  831.     int
  832. mch_can_exe(name)
  833.     char_u    *name;
  834. {
  835.     /* TODO */
  836.     return -1;
  837. }
  838. #endif
  839.  
  840. /*
  841.  * Check what "name" is:
  842.  * NODE_NORMAL: file or directory (or doesn't exist)
  843.  * NODE_WRITABLE: writable device, socket, fifo, etc.
  844.  * NODE_OTHER: non-writable things
  845.  */
  846.     int
  847. mch_nodetype(name)
  848.     char_u    *name;
  849. {
  850.     /* TODO */
  851.     return NODE_NORMAL;
  852. }
  853.  
  854.     void
  855. mch_early_init()
  856. {
  857. }
  858.  
  859. /*
  860.  * Careful: mch_exit() may be called before mch_init()!
  861.  */
  862.     void
  863. mch_exit(r)
  864.     int            r;
  865. {
  866.     if (raw_in)                /* put terminal in 'normal' mode */
  867.     {
  868.     settmode(TMODE_COOK);
  869.     stoptermcap();
  870.     }
  871.     out_char('\n');
  872.     if (raw_out)
  873.     {
  874.     if (term_console)
  875.     {
  876.         win_resize_off();        /* window resize events de-activated */
  877.         if (size_set)
  878.         OUT_STR("\233t\233u");    /* reset window size (CSI t CSI u) */
  879.     }
  880.     out_flush();
  881.     }
  882.  
  883. #ifdef FEAT_TITLE
  884.     mch_restore_title(3);        /* restore window title */
  885. #endif
  886.  
  887.     ml_close_all(TRUE);            /* remove all memfiles */
  888.  
  889. #ifdef FEAT_ARP
  890.     if (ArpBase)
  891.     CloseLibrary((struct Library *) ArpBase);
  892. #endif
  893.     if (close_win)
  894.     Close(raw_in);
  895.     if (r)
  896.     printf(_("Vim exiting with %d\n"), r); /* somehow this makes :cq work!? */
  897.     exit(r);
  898. }
  899.  
  900. /*
  901.  * This is a routine for setting a given stream to raw or cooked mode on the
  902.  * Amiga . This is useful when you are using Lattice C to produce programs
  903.  * that want to read single characters with the "getch()" or "fgetc" call.
  904.  *
  905.  * Written : 18-Jun-87 By Chuck McManis.
  906.  */
  907.  
  908. #define MP(xx)    ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type)
  909.  
  910. /*
  911.  * Function mch_settmode() - Convert the specified file pointer to 'raw' or
  912.  * 'cooked' mode. This only works on TTY's.
  913.  *
  914.  * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means
  915.  *    getch() will return immediately rather than wait for a return. You
  916.  *    lose editing features though.
  917.  *
  918.  * Cooked: This function returns the designate file pointer to it's normal,
  919.  *    wait for a <CR> mode. This is exactly like raw() except that
  920.  *    it sends a 0 to the console to make it back into a CON: from a RAW:
  921.  */
  922.     void
  923. mch_settmode(tmode)
  924.     int        tmode;
  925. {
  926.     if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE,
  927.                       tmode == TMODE_RAW ? -1L : 0L) == 0)
  928.     mch_errmsg(_("cannot change console mode ?!\n"));
  929. }
  930.  
  931. /*
  932.  * set screen mode, always fails.
  933.  */
  934.     int
  935. mch_screenmode(arg)
  936.     char_u    *arg;
  937. {
  938.     EMSG(_("E359: Screen mode setting not supported"));
  939.     return FAIL;
  940. }
  941.  
  942. /*
  943.  * Code for this routine came from the following :
  944.  *
  945.  * ConPackets.c -  C. Scheppner, A. Finkel, P. Lindsay    CBM
  946.  *   DOS packet example
  947.  *   Requires 1.2
  948.  *
  949.  * Found on Fish Disk 56.
  950.  *
  951.  * Heavely modified by mool.
  952.  */
  953.  
  954. #include <devices/conunit.h>
  955.  
  956. /*
  957.  * try to get the real window size
  958.  * return FAIL for failure, OK otherwise
  959.  */
  960.     int
  961. mch_get_shellsize()
  962. {
  963.     struct ConUnit  *conUnit;
  964.     char        id_a[sizeof(struct InfoData) + 3];
  965.     struct InfoData *id;
  966.  
  967.     if (!term_console)    /* not an amiga window */
  968.     return FAIL;
  969.  
  970.     /* insure longword alignment */
  971.     id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  972.  
  973.     /*
  974.      * Should make console aware of real window size, not the one we set.
  975.      * Unfortunately, under DOS 2.0x this redraws the window and it
  976.      * is rarely needed, so we skip it now, unless we changed the size.
  977.      */
  978.     if (size_set)
  979.     OUT_STR("\233t\233u");    /* CSI t CSI u */
  980.     out_flush();
  981.  
  982.     if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0
  983.         || (wb_window = (struct Window *)id->id_VolumeNode) == NULL)
  984.     {
  985.     /* it's not an amiga window, maybe aux device */
  986.     /* terminal type should be set */
  987.     term_console = FALSE;
  988.     return FAIL;
  989.     }
  990.     if (oldwindowtitle == NULL)
  991.     oldwindowtitle = (char_u *)wb_window->Title;
  992.     if (id->id_InUse == (BPTR)NULL)
  993.     {
  994.     mch_errmsg(_("mch_get_shellsize: not a console??\n"));
  995.     return FAIL;
  996.     }
  997.     conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit;
  998.  
  999.     /* get window size */
  1000.     Rows = conUnit->cu_YMax + 1;
  1001.     Columns = conUnit->cu_XMax + 1;
  1002.     if (Rows < 0 || Rows > 200)        /* cannot be an amiga window */
  1003.     {
  1004.     Columns = 80;
  1005.     Rows = 24;
  1006.     term_console = FALSE;
  1007.     return FAIL;
  1008.     }
  1009.  
  1010.     return OK;
  1011. }
  1012.  
  1013. /*
  1014.  * Try to set the real window size to Rows and Columns.
  1015.  */
  1016.     void
  1017. mch_set_shellsize()
  1018. {
  1019.     if (term_console)
  1020.     {
  1021.     size_set = TRUE;
  1022.     out_char(CSI);
  1023.     out_num((long)Rows);
  1024.     out_char('t');
  1025.     out_char(CSI);
  1026.     out_num((long)Columns);
  1027.     out_char('u');
  1028.     out_flush();
  1029.     }
  1030. }
  1031.  
  1032. /*
  1033.  * Rows and/or Columns has changed.
  1034.  */
  1035.     void
  1036. mch_new_shellsize()
  1037. {
  1038.     /* Nothing to do. */
  1039. }
  1040.  
  1041. /*
  1042.  * out_num - output a (big) number fast
  1043.  */
  1044.     static void
  1045. out_num(n)
  1046.     long    n;
  1047. {
  1048.     OUT_STR_NF(tltoa((unsigned long)n));
  1049. }
  1050.  
  1051. #ifndef AZTEC_C
  1052. /*
  1053.  * Sendpacket.c
  1054.  *
  1055.  * An invaluable addition to your Amiga.lib file. This code sends a packet to
  1056.  * the given message port. This makes working around DOS lots easier.
  1057.  *
  1058.  * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
  1059.  * however that you may wish to add it to Amiga.Lib, to do so, compile it and
  1060.  * say 'oml lib:amiga.lib -r sendpacket.o'
  1061.  */
  1062.  
  1063. /* #include <proto/exec.h> */
  1064. /* #include <proto/dos.h> */
  1065. #include <exec/memory.h>
  1066.  
  1067. /*
  1068.  * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy
  1069.  * Finkel. This function will send a packet of the given type to the Message
  1070.  * Port supplied.
  1071.  */
  1072.  
  1073.     static long
  1074. dos_packet(pid, action, arg)
  1075.     struct MsgPort *pid;    /* process indentifier ... (handlers message port) */
  1076.     long        action, /* packet type ... (what you want handler to do)   */
  1077.             arg;    /* single argument */
  1078. {
  1079. # ifdef FEAT_ARP
  1080.     struct MsgPort        *replyport;
  1081.     struct StandardPacket   *packet;
  1082.     long            res1;
  1083.  
  1084.     if (dos2)
  1085. # endif
  1086.     return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L);    /* use 2.0 function */
  1087. # ifdef FEAT_ARP
  1088.  
  1089.     replyport = (struct MsgPort *) CreatePort(NULL, 0);    /* use arp function */
  1090.     if (!replyport)
  1091.     return (0);
  1092.  
  1093.     /* Allocate space for a packet, make it public and clear it */
  1094.     packet = (struct StandardPacket *)
  1095.     AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
  1096.     if (!packet) {
  1097.     DeletePort(replyport);
  1098.     return (0);
  1099.     }
  1100.     packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
  1101.     packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  1102.     packet->sp_Pkt.dp_Port = replyport;
  1103.     packet->sp_Pkt.dp_Type = action;
  1104.     packet->sp_Pkt.dp_Arg1 = arg;
  1105.  
  1106.     PutMsg(pid, (struct Message *)packet);    /* send packet */
  1107.  
  1108.     WaitPort(replyport);
  1109.     GetMsg(replyport);
  1110.  
  1111.     res1 = packet->sp_Pkt.dp_Res1;
  1112.  
  1113.     FreeMem(packet, (long) sizeof(struct StandardPacket));
  1114.     DeletePort(replyport);
  1115.  
  1116.     return (res1);
  1117. # endif
  1118. }
  1119. #endif
  1120.  
  1121. /*
  1122.  * Call shell.
  1123.  * Return error number for failure, 0 otherwise
  1124.  */
  1125.     int
  1126. mch_call_shell(cmd, options)
  1127.     char_u    *cmd;
  1128.     int        options;    /* SHELL_*, see vim.h */
  1129. {
  1130.     BPTR    mydir;
  1131.     int        x;
  1132. #ifdef AZTEC_C
  1133.     int        use_execute;
  1134.     char_u    *shellcmd = NULL;
  1135.     char_u    *shellarg;
  1136. #endif
  1137.     int        retval = 0;
  1138.  
  1139.     if (close_win)
  1140.     {
  1141.     /* if Vim opened a window: Executing a shell may cause crashes */
  1142.     EMSG(_("E360: Cannot execute shell with -f option"));
  1143.     return -1;
  1144.     }
  1145.  
  1146.     if (term_console)
  1147.     win_resize_off();        /* window resize events de-activated */
  1148.     out_flush();
  1149.  
  1150.     if (options & SHELL_COOKED)
  1151.     settmode(TMODE_COOK);        /* set to normal mode */
  1152.     mydir = Lock((UBYTE *)"", (long)ACCESS_READ);   /* remember current dir */
  1153.  
  1154. #if !defined(AZTEC_C)            /* not tested very much */
  1155.     if (cmd == NULL)
  1156.     {
  1157. # ifdef FEAT_ARP
  1158.     if (dos2)
  1159. # endif
  1160.         x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1161. # ifdef FEAT_ARP
  1162.     else
  1163.         x = Execute(p_sh, raw_in, raw_out);
  1164. # endif
  1165.     }
  1166.     else
  1167.     {
  1168. # ifdef FEAT_ARP
  1169.     if (dos2)
  1170. # endif
  1171.         x = SystemTags((char *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1172. # ifdef FEAT_ARP
  1173.     else
  1174.         x = Execute((char *)cmd, 0L, raw_out);
  1175. # endif
  1176.     }
  1177. # ifdef FEAT_ARP
  1178.     if ((dos2 && x < 0) || (!dos2 && !x))
  1179. # else
  1180.     if (x < 0)
  1181. # endif
  1182.     {
  1183.     MSG_PUTS(_("Cannot execute "));
  1184.     if (cmd == NULL)
  1185.     {
  1186.         MSG_PUTS(_("shell "));
  1187.         msg_outtrans(p_sh);
  1188.     }
  1189.     else
  1190.         msg_outtrans(cmd);
  1191.     msg_putchar('\n');
  1192.     retval = -1;
  1193.     }
  1194. # ifdef FEAT_ARP
  1195.     else if (!dos2 || x)
  1196. # else
  1197.     else if (x)
  1198. # endif
  1199.     {
  1200.     if (x = IoErr())
  1201.     {
  1202.         if (!(options & SHELL_SILENT))
  1203.         {
  1204.         msg_putchar('\n');
  1205.         msg_outnum((long)x);
  1206.         MSG_PUTS(_(" returned\n"));
  1207.         }
  1208.         retval = x;
  1209.     }
  1210.     }
  1211. #else    /* else part is for AZTEC_C */
  1212.     if (p_st >= 4 || (p_st >= 2 && !(options & SHELL_FILTER)))
  1213.     use_execute = 1;
  1214.     else
  1215.     use_execute = 0;
  1216.     if (!use_execute)
  1217.     {
  1218.     /*
  1219.      * separate shell name from argument
  1220.      */
  1221.     shellcmd = vim_strsave(p_sh);
  1222.     if (shellcmd == NULL)        /* out of memory, use Execute */
  1223.         use_execute = 1;
  1224.     else
  1225.     {
  1226.         shellarg = skiptowhite(shellcmd);    /* find start of arguments */
  1227.         if (*shellarg != NUL)
  1228.         {
  1229.         *shellarg++ = NUL;
  1230.         shellarg = skipwhite(shellarg);
  1231.         }
  1232.     }
  1233.     }
  1234.     if (cmd == NULL)
  1235.     {
  1236.     if (use_execute)
  1237.     {
  1238. # ifdef FEAT_ARP
  1239.         if (dos2)
  1240. # endif
  1241.         x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1242. # ifdef FEAT_ARP
  1243.         else
  1244.         x = !Execute((UBYTE *)p_sh, raw_in, raw_out);
  1245. # endif
  1246.     }
  1247.     else
  1248.         x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, NULL);
  1249.     }
  1250.     else if (use_execute)
  1251.     {
  1252. # ifdef FEAT_ARP
  1253.     if (dos2)
  1254. # endif
  1255.         x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1256. # ifdef FEAT_ARP
  1257.     else
  1258.         x = !Execute((UBYTE *)cmd, 0L, raw_out);
  1259. # endif
  1260.     }
  1261.     else if (p_st & 1)
  1262.     x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg,
  1263.                                (char *)cmd, NULL);
  1264.     else
  1265.     x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg,
  1266.                        (char *)p_shcf, (char *)cmd, NULL);
  1267. # ifdef FEAT_ARP
  1268.     if ((dos2 && x < 0) || (!dos2 && x))
  1269. # else
  1270.     if (x < 0)
  1271. # endif
  1272.     {
  1273.     MSG_PUTS(_("Cannot execute "));
  1274.     if (use_execute)
  1275.     {
  1276.         if (cmd == NULL)
  1277.         msg_outtrans(p_sh);
  1278.         else
  1279.         msg_outtrans(cmd);
  1280.     }
  1281.     else
  1282.     {
  1283.         MSG_PUTS(_("shell "));
  1284.         msg_outtrans(shellcmd);
  1285.     }
  1286.     msg_putchar('\n');
  1287.     retval = -1;
  1288.     }
  1289.     else
  1290.     {
  1291.     if (use_execute)
  1292.     {
  1293. # ifdef FEAT_ARP
  1294.         if (!dos2 || x)
  1295. # else
  1296.         if (x)
  1297. # endif
  1298.         x = IoErr();
  1299.     }
  1300.     else
  1301.         x = wait();
  1302.     if (x)
  1303.     {
  1304.         if (!(options & SHELL_SILENT) && !emsg_silent)
  1305.         {
  1306.         msg_putchar('\n');
  1307.         msg_outnum((long)x);
  1308.         MSG_PUTS(_(" returned\n"));
  1309.         }
  1310.         retval = x;
  1311.     }
  1312.     }
  1313.     vim_free(shellcmd);
  1314. #endif    /* AZTEC_C */
  1315.  
  1316.     if (mydir = CurrentDir(mydir))    /* make sure we stay in the same directory */
  1317.     UnLock(mydir);
  1318.     settmode(TMODE_RAW);        /* set to raw mode */
  1319. #ifdef FEAT_TITLE
  1320.     resettitle();
  1321. #endif
  1322.     if (term_console)
  1323.     win_resize_on();        /* window resize events activated */
  1324.     return retval;
  1325. }
  1326.  
  1327. /*
  1328.  * check for an "interrupt signal"
  1329.  * We only react to a CTRL-C, but also clear the other break signals to avoid
  1330.  * trouble with lattice-c programs.
  1331.  */
  1332.     void
  1333. mch_breakcheck()
  1334. {
  1335.    if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C)
  1336.     got_int = TRUE;
  1337. }
  1338.  
  1339. /* this routine causes manx to use this Chk_Abort() rather than it's own */
  1340. /* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
  1341. /* is zero).  Since we want to check for our own ^C's             */
  1342.  
  1343. #ifdef _DCC
  1344. #define Chk_Abort chkabort
  1345. #endif
  1346.  
  1347. #ifdef LATTICE
  1348. void __regargs __chkabort(void);
  1349.  
  1350. void __regargs __chkabort(void)
  1351. {}
  1352.  
  1353. #else
  1354.     long
  1355. Chk_Abort(void)
  1356. {
  1357.     return(0L);
  1358. }
  1359. #endif
  1360.  
  1361. /*
  1362.  * mch_expandpath() - this code does wild-card pattern matching using the arp
  1363.  *              routines.
  1364.  *
  1365.  * "pat" has backslashes before chars that are not to be expanded.
  1366.  * Returns the number of matches found.
  1367.  *
  1368.  * This is based on WildDemo2.c (found in arp1.1 distribution).
  1369.  * That code's copyright follows:
  1370.  *    Copyright (c) 1987, Scott Ballantyne
  1371.  *    Use and abuse as you please.
  1372.  */
  1373.  
  1374. #define ANCHOR_BUF_SIZE (512)
  1375. #define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
  1376.  
  1377.     int
  1378. mch_expandpath(gap, pat, flags)
  1379.     garray_T    *gap;
  1380.     char_u    *pat;
  1381.     int        flags;        /* EW_* flags */
  1382. {
  1383.     struct AnchorPath    *Anchor;
  1384.     LONG        Result;
  1385.     char_u        *starbuf, *sp, *dp;
  1386.     int            start_len;
  1387.     int            matches;
  1388.  
  1389.     start_len = gap->ga_len;
  1390.  
  1391.     /* Get our AnchorBase */
  1392.     Anchor = (struct AnchorPath *)alloc_clear((unsigned)ANCHOR_SIZE);
  1393.     if (Anchor == NULL)
  1394.     return 0;
  1395.  
  1396.     Anchor->ap_Strlen = ANCHOR_BUF_SIZE;  /* ap_Length not supported anymore */
  1397. #ifdef APF_DODOT
  1398.     Anchor->ap_Flags = APF_DODOT | APF_DOWILD;    /* allow '.' for current dir */
  1399. #else
  1400.     Anchor->ap_Flags = APF_DoDot | APF_DoWild;    /* allow '.' for current dir */
  1401. #endif
  1402.  
  1403. #ifdef FEAT_ARP
  1404.     if (dos2)
  1405.     {
  1406. #endif
  1407.     /* hack to replace '*' by '#?' */
  1408.     starbuf = alloc((unsigned)(2 * STRLEN(pat) + 1));
  1409.     if (starbuf == NULL)
  1410.         goto Return;
  1411.     for (sp = pat, dp = starbuf; *sp; ++sp)
  1412.     {
  1413.         if (*sp == '*')
  1414.         {
  1415.         *dp++ = '#';
  1416.         *dp++ = '?';
  1417.         }
  1418.         else
  1419.         *dp++ = *sp;
  1420.     }
  1421.     *dp = NUL;
  1422.     Result = MatchFirst((UBYTE *)starbuf, Anchor);
  1423.     vim_free(starbuf);
  1424. #ifdef FEAT_ARP
  1425.     }
  1426.     else
  1427.     Result = FindFirst((char *)pat, Anchor);
  1428. #endif
  1429.  
  1430.     /*
  1431.      * Loop to get all matches.
  1432.      */
  1433.     while (Result == 0)
  1434.     {
  1435.     addfile(gap, (char_u *)Anchor->ap_Buf, flags);
  1436. #ifdef FEAT_ARP
  1437.     if (dos2)
  1438. #endif
  1439.         Result = MatchNext(Anchor);
  1440. #ifdef FEAT_ARP
  1441.     else
  1442.         Result = FindNext(Anchor);
  1443. #endif
  1444.     }
  1445.     matches = gap->ga_len - start_len;
  1446.  
  1447.     if (Result == ERROR_BUFFER_OVERFLOW)
  1448.     EMSG(_("ANCHOR_BUF_SIZE too small."));
  1449.     else if (matches == 0 && Result != ERROR_OBJECT_NOT_FOUND
  1450.               && Result != ERROR_DEVICE_NOT_MOUNTED
  1451.               && Result != ERROR_NO_MORE_ENTRIES)
  1452.     EMSG(_("I/O ERROR"));
  1453.  
  1454.     /*
  1455.      * Sort the files for this pattern.
  1456.      */
  1457.     if (matches)
  1458.     qsort((void *)(((char_u **)gap->ga_data) + start_len),
  1459.                   (size_t)matches, sizeof(char_u *), sortcmp);
  1460.  
  1461.     /* Free the wildcard stuff */
  1462. #ifdef FEAT_ARP
  1463.     if (dos2)
  1464. #endif
  1465.     MatchEnd(Anchor);
  1466. #ifdef FEAT_ARP
  1467.     else
  1468.     FreeAnchorChain(Anchor);
  1469. #endif
  1470.  
  1471. Return:
  1472.     vim_free(Anchor);
  1473.  
  1474.     return matches;
  1475. }
  1476.  
  1477.     static int
  1478. sortcmp(a, b)
  1479.     char **a, **b;
  1480. {
  1481.     return pathcmp(*a, *b);
  1482. }
  1483.  
  1484. /*
  1485.  * Return TRUE if "p" has wildcards that can be expanded by mch_expandpath().
  1486.  */
  1487.     int
  1488. mch_has_exp_wildcard(p)
  1489.     char_u *p;
  1490. {
  1491.     for ( ; *p; ++p)
  1492.     {
  1493.     if (*p == '\\' && p[1] != NUL)
  1494.         ++p;
  1495.     else
  1496.         if (vim_strchr((char_u *)"*?[(#", *p) != NULL)
  1497.         return TRUE;
  1498.     }
  1499.     return FALSE;
  1500. }
  1501.  
  1502.     int
  1503. mch_has_wildcard(p)
  1504.     char_u *p;
  1505. {
  1506.     for ( ; *p; ++p)
  1507.     {
  1508.     if (*p == '\\' && p[1] != NUL)
  1509.         ++p;
  1510.     else
  1511.         if (vim_strchr((char_u *)
  1512. #  ifdef VIM_BACKTICK
  1513.                     "*?[(#$`"
  1514. #  else
  1515.                     "*?[(#$"
  1516. #  endif
  1517.                         , *p) != NULL
  1518.             || (*p == '~' && p[1] != NUL))
  1519.         return TRUE;
  1520.     }
  1521.     return FALSE;
  1522. }
  1523.  
  1524. /*
  1525.  * With AmigaDOS 2.0 support for reading local environment variables
  1526.  *
  1527.  * Two buffers are allocated:
  1528.  * - A big one to do the expansion into.  It is freed before returning.
  1529.  * - A small one to hold the return value.  It is kept until the next call.
  1530.  */
  1531.     char_u *
  1532. mch_getenv(var)
  1533.     char_u *var;
  1534. {
  1535.     int            len;
  1536.     UBYTE        *buf;        /* buffer to expand in */
  1537.     char_u        *retval;        /* return value */
  1538.     static char_u   *alloced = NULL;    /* allocated memory */
  1539.  
  1540. #ifdef FEAT_ARP
  1541.     if (!dos2)
  1542.     retval = (char_u *)getenv((char *)var);
  1543.     else
  1544. #endif
  1545.     {
  1546.     vim_free(alloced);
  1547.     alloced = NULL;
  1548.     retval = NULL;
  1549.  
  1550.     buf = alloc(IOSIZE);
  1551.     if (buf == NULL)
  1552.         return NULL;
  1553.  
  1554.     len = GetVar((UBYTE *)var, buf, (long)(IOSIZE - 1), (long)0);
  1555.     if (len >= 0)
  1556.     {
  1557.         retval = vim_strsave((char_u *)buf);
  1558.         alloced = retval;
  1559.     }
  1560.  
  1561.     vim_free(buf);
  1562.     }
  1563.  
  1564.     /* if $VIM is not defined, use "vim:" instead */
  1565.     if (retval == NULL && STRCMP(var, "VIM") == 0)
  1566.     retval = (char_u *)"vim:";
  1567.  
  1568.     return retval;
  1569. }
  1570.  
  1571. /*
  1572.  * Amiga version of setenv() with AmigaDOS 2.0 support.
  1573.  */
  1574. /* ARGSUSED */
  1575.     int
  1576. mch_setenv(var, value, x)
  1577.     char *var;
  1578.     char *value;
  1579.     int     x;
  1580. {
  1581. #ifdef FEAT_ARP
  1582.     if (!dos2)
  1583.     return setenv(var, value);
  1584. #endif
  1585.  
  1586.     if (SetVar((UBYTE *)var, (UBYTE *)value, (LONG)-1, (ULONG)GVF_LOCAL_ONLY))
  1587.     return 0;   /* success */
  1588.     return -1;        /* failure */
  1589. }
  1590.